package com.eso.frame.core;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * DAO实现类
 * User: Noah.Rong
 * Version: 0.1,  2012-05-22 16:24
 */
@Component
public class DaoImpl extends HibernateDaoSupport implements IDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    public DaoImpl(SessionFactory sessionFactory) {
        super.setSessionFactory(sessionFactory);
    }

    public JdbcTemplate getJdbcTemplate() {
        return this.jdbcTemplate;
    }

    public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
        return new NamedParameterJdbcTemplate(this.getJdbcTemplate());
    }

    public Object get(Class entityClass, Serializable id) {
        return this.getHibernateTemplate().get(entityClass, id);
    }

    public Object get(String entityName, Serializable id) {
        return this.getHibernateTemplate().get(entityName, id);
    }

    public Object load(Class entityClass, Serializable id) throws DataAccessException {
        return this.getHibernateTemplate().load(entityClass, id);

    }

    public Object load(String entityName, Serializable id) throws DataAccessException {
        return this.getHibernateTemplate().load(entityName, id);
    }

    public List loadAll(Class entityClass) throws DataAccessException {
        return this.getHibernateTemplate().loadAll(entityClass);
    }

    public void refresh(Object entity) {
        this.getHibernateTemplate().refresh(entity);
    }

    public boolean contains(Object entity) throws DataAccessException {
        return this.getHibernateTemplate().contains(entity);

    }

    public void evict(Object entity) throws DataAccessException {
        this.getHibernateTemplate().evict(entity);

    }

    public void load(Object entity, Serializable id) throws DataAccessException {
        this.getHibernateTemplate().load(entity, id);
    }

    public List find(String queryString, Object value) {
        return this.getHibernateTemplate().find(queryString, value);
    }

    public List find(String queryString, Object... values) {
        return this.getHibernateTemplate().find(queryString, values);
    }

    public Long findCount(final String queryHql, final Map<String, Object> paramsMap){
        return (Long) this.getHibernateTemplate().executeFind(new HibernateCallback<Object>() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Query query = session.createQuery(queryHql);
                query.setProperties(paramsMap);
                return query.list();
            }
        }).get(0);
    }


    public List findByNamedParam(String queryString, String paramName, Object value) {
        return this.getHibernateTemplate().findByNamedParam(queryString, paramName, value);
    }

    public List findByNamedParam(String queryString, String[] paramNames, Object[] values) {
        return this.getHibernateTemplate().findByNamedParam(queryString, paramNames, values);
    }

    public List findByValueBean(String queryString, Object valueBean) {
        return this.getHibernateTemplate().findByValueBean(queryString, valueBean);  //To change body of implemented methods use File | Settings | File Templates.
    }

    public List findByCriteria(DetachedCriteria criteria) {
        return this.getHibernateTemplate().findByCriteria(criteria);
    }

    public List findByCriteria(DetachedCriteria criteria, int firstResult, int maxResults) {
        return this.getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults);  //To change body of implemented methods use File | Settings | File Templates.
    }

    public List findByExample(Object exampleEntity) {
        return this.getHibernateTemplate().findByExample(exampleEntity);  //To change body of implemented methods use File | Settings | File Templates.
    }

    public List findByExample(String entityName, Object exampleEntity) {
        return this.getHibernateTemplate().findByExample(entityName, exampleEntity);  //To change body of implemented methods use File | Settings | File Templates.
    }

    public List findByExample(Object exampleEntity, int firstResult, int maxResults) {
        return this.getHibernateTemplate().findByExample(exampleEntity, firstResult, maxResults);  //To change body of implemented methods use File | Settings | File Templates.
    }

    public Iterator iterate(String queryString) {
        return this.getHibernateTemplate().iterate(queryString);  //To change body of implemented methods use File | Settings | File Templates.
    }

    public Iterator iterate(String queryString, Object value) {
        return this.getHibernateTemplate().iterate(queryString, value);  //To change body of implemented methods use File | Settings | File Templates.
    }

    public Iterator iterate(String queryString, Object... values) {
        return this.getHibernateTemplate().iterate(queryString, values);  //To change body of implemented methods use File | Settings | File Templates.
    }

    public Serializable save(Object object) {
        return this.getHibernateTemplate().save(object);
    }

    public Serializable save(String entityName, Object entity) {
        return this.getHibernateTemplate().save(entityName, entity);  //To change body of implemented methods use File | Settings | File Templates.
    }

    public void update(Object entity) {
        this.getHibernateTemplate().update(entity);
    }

    public void update(String entityName, Object entity) {
        this.getHibernateTemplate().update(entityName, entity);
    }

    public void saveOrUpdate(Object entity) {
        this.getHibernateTemplate().saveOrUpdate(entity);
    }

    public void saveOrUpdateAll(Collection entities) {
        this.getHibernateTemplate().saveOrUpdateAll(entities);
    }

    public void persist(Object entity) {
        this.getHibernateTemplate().persist(entity);
    }

    public Object merge(Object entity) {
        return this.getHibernateTemplate().merge(entity);
    }

    public void deleteAll(Collection entities) {
        this.getHibernateTemplate().deleteAll(entities);
    }

    public List find(String queryString) {
        return this.getHibernateTemplate().find(queryString);
    }

    public List find(String queryString, int firstResult, int maxResults) {
        return this.find(queryString, null, firstResult, maxResults);
    }

    public List find(String queryString, Object[] par, int firstResult, int maxResults) {
        return this.findPageByHql(queryString, par, firstResult, maxResults);  //To change body of implemented methods use File | Settings | File Templates.
    }

    public List findPageByHql(final String queryString, final Object[] params, final Integer firstResult, final Integer pageSize) {
        return this.getHibernateTemplate().executeFind(new HibernateCallback<Object>() {
            public Object doInHibernate(Session session) throws HibernateException, SQLException {
                Query query = session.createQuery(queryString);
                if (params != null) {
                    for (int i = 0, s = params.length; i < s; i++) {
                        query.setParameter(i, params[i]);
                    }
                }
                query.setFirstResult(firstResult);
                query.setMaxResults(pageSize);
                return query.list();
            }
        });

    }

    public Integer execute(final String hql, final Object[] params) {
        return this.getHibernateTemplate().execute(new HibernateCallback<Integer>() {
            public Integer doInHibernate(Session session) throws HibernateException, SQLException {
                Query query = session.createQuery(hql);
                if (params != null) {
                    for (int i = 0, s = params.length; i < s; i++) {
                        query.setParameter(i, params[i]);
                    }
                }
                return query.executeUpdate();
            }
        });
    }

    public void delete(Object entity) {
        getHibernateTemplate().delete(entity);
    }
}
